use log::{Level, Metadata, Record, debug, error, info};
use std::fs::File;
use std::io::{Read, Write};
use std::net::{TcpListener, TcpStream, ToSocketAddrs};
use std::thread::spawn;

const PROXY_SUCCESS: &str = "HTTP/1.1 200 Connection Established\r\n\r\n";

const PROXY_FAIL: &str = "HTTP/1.1 502 Bad Gateway\r\n\r\n";
struct SimpleLogger;

impl log::Log for SimpleLogger {
    fn enabled(&self, metadata: &Metadata) -> bool {
        metadata.level() <= Level::Info
    }

    fn log(&self, record: &Record) {
        if self.enabled(record.metadata()) {
            println!("[ {} ] - {}", record.level(), record.args());
        }
    }

    fn flush(&self) {}
}
use log::{LevelFilter, SetLoggerError};
use my_lib::sock_to_sock;

static LOGGER: SimpleLogger = SimpleLogger;

pub fn init_log() -> Result<(), SetLoggerError> {
    log::set_logger(&LOGGER).map(|()| log::set_max_level(LevelFilter::Info))
}
struct Config {
    filename: String,
    config: Vec<String>,
    config_server_bind: Option<String>,
}
impl Config {
    fn new(filename: String) -> Self {
        let config = Config::read_config(filename.clone()).unwrap();
        Self {
            filename,
            config: config.clone(),
            config_server_bind: Self::read_config_line(&config, 0),
        }
    }
    fn read_config(filename: String) -> Result<Vec<String>, std::io::Error> {
        let mut file = File::open(&filename)?;
        let mut buffer = String::new();
        file.read_to_string(&mut buffer)?;
        Ok(buffer
            .split(|i| i == '\n')
            .filter(|l| !l.starts_with(|i| i == '#'))
            .map(|i| i.to_string())
            .collect::<Vec<_>>())
    }

    fn read_config_line(config: &Vec<String>, line: usize) -> Option<String> {
        if config.len() > 0 {
            Some(config[line].clone())
        } else {
            None
        }
    }

    pub fn filename(&self) -> &str {
        &self.filename
    }

    pub fn config(&self) -> &Vec<String> {
        &self.config
    }

    pub fn config_server_bind(&self) -> &Option<String> {
        &self.config_server_bind
    }
}

fn main() {
    init_log();
    let filename = "config".to_owned();
    let config = Config::new(filename.trim().to_string());
    let listener = TcpListener::bind(config.config_server_bind().clone().unwrap()).unwrap();

    let mut thread_buf = vec![];

    for stream in listener.incoming() {
        match stream {
            Ok(tcpsock) => {
                thread_buf.push(spawn(move || handle(tcpsock)));
            }
            _ => {}
        }
    }
}

fn handle(mut client_sock: TcpStream) {
    let mut buffer = vec![0; 1500];
    let siz = client_sock.read(&mut buffer).unwrap();
    let request = String::from_utf8_lossy(&buffer[0..siz]);
    info!("{}", request);
    // 解析请求行 获取 method 和 host
    let parts: Vec<&str> = request.split_whitespace().collect();
    if parts.len() < 3 {
        return;
    }
    let method = parts[0];
    let host = match parts
        .iter()
        .find(|s| s.ends_with(":443") || s.ends_with(":80"))
    {
        Some(h) => {
            info!("uri is {}", h);
            h.to_string()
        }
        None => {
            let mut h = parts[4].to_owned();
            if parts[1].starts_with("https") {
                h.push_str(":443");
            } else {
                h.push_str(":80");
            }
            info!("uri is {}", h);
            h
        }
    };
    info!("method is {}", method);
    info!("host is {}", host);
    // DNS 解析
    let ips = host.to_socket_addrs().unwrap();
    let ip = ips.filter(|i| i.is_ipv4()).collect::<Vec<_>>();
    let ip = ip[0];
    info!("use ip {:?}", ip);
    // CONNECT 请求处理链接
    let mut remote = if method == "CONNECT" {
        let mut remote = match TcpStream::connect(ip) {
            Ok(s) => {
                debug!("success connect");
                s
            }
            Err(_) => {
                // let _ = client_sock.write_all(b"HTTP/1.1 502 Bad Gateway\r\n\r\n");
                let _ = client_sock.write_all(PROXY_FAIL.as_bytes());
                return;
            }
        };

        // let _ = client_sock.write_all(b"HTTP/1.1 200 Connection Established\r\n\r\n");
        let _ = client_sock.write_all(PROXY_SUCCESS.as_bytes());
        remote
    } else {
        // GET 请求处理链接
        let mut remote = match TcpStream::connect(ip) {
            Ok(s) => {
                debug!("success connect");
                s
            }
            Err(_) => {
                return;
            }
        };
        remote.write_all(&buffer[0..siz]).unwrap();
        remote
    };
    // 双向数据透传
    // 客户端 -> 远程服务器
    let mut client_clone = client_sock.try_clone().unwrap();
    let mut remote_clone = remote.try_clone().unwrap();
    let client_to_remote = sock_to_sock!(client_sock, remote);
    // 远程服务器 -> 客户端
    let remote_to_client = sock_to_sock!(remote_clone, client_clone);
    let _ = client_to_remote.join();
    let _ = remote_to_client.join();
}
